let ops = ops::TestOptions {
no_run: options.flag_no_run,
+ no_fail_fast: false,
compile_opts: ops::CompileOptions {
config: config,
jobs: options.flag_jobs,
flag_quiet: bool,
flag_color: Option<String>,
flag_release: bool,
+ flag_no_fail_fast: bool,
}
pub const USAGE: &'static str = "
-v, --verbose Use verbose output
-q, --quiet No output printed to stdout
--color WHEN Coloring: auto, always, never
+ --no-fail-fast Run all tests regardless of failure
All of the trailing arguments are passed to the test binaries generated for
filtering tests and generally providing options configuring how they run. For
let ops = ops::TestOptions {
no_run: options.flag_no_run,
+ no_fail_fast: options.flag_no_fail_fast,
compile_opts: ops::CompileOptions {
config: config,
jobs: options.flag_jobs,
pub struct TestOptions<'a> {
pub compile_opts: ops::CompileOptions<'a>,
pub no_run: bool,
+ pub no_fail_fast: bool,
}
#[allow(deprecated)] // connect => join in 1.3
compile.tests.sort();
let cwd = config.cwd();
+ let mut errors = Vec::new();
for &(_, ref exe) in &compile.tests {
let to_display = match util::without_prefix(exe, &cwd) {
Some(path) => path,
}));
match ExecEngine::exec(&mut ProcessEngine, cmd) {
Ok(()) => {}
- Err(e) => return Ok(Err(e))
+ Err(e) => {
+ errors.push(e);
+ if !options.no_fail_fast {
+ break
+ }
+ }
}
}
+ if errors.is_empty() {
+ Ok(Ok(compile))
+ } else {
+ // errors.len() can be > 1, if --no-fail-fast is present.
+ // It would be cleaner to return the list of errors instead of just the last one.
+ Ok(Err(errors.pop().unwrap()))
+ }
- Ok(Ok(compile))
}